/***************************************************************************
    File                 : columncommands.h
    Project              : AlphaPlot
    Description          : Commands to be called by Column to modify
 Column::Private
    --------------------------------------------------------------------
    Copyright            : (C) 2007-2009 Tilman Benkert (thzs*gmx.net)
                           (replace * with @ in the email addresses)

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/

#ifndef COLUMNCOMMANDS_H
#define COLUMNCOMMANDS_H

#include <QUndoCommand>
#include <QStringList>
#include "core/column/Column.h"
#include "core/AbstractSimpleFilter.h"
#include "lib/IntervalAttribute.h"

///////////////////////////////////////////////////////////////////////////
// class ColumnSetModeCmd
///////////////////////////////////////////////////////////////////////////
//! Set the column mode
class ColumnSetModeCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetModeCmd(Column::Private* col, AlphaPlot::ColumnMode mode,
                   AbstractFilter* conversion_filter, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetModeCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The previous mode
  AlphaPlot::ColumnMode d_old_mode;
  //! The new mode
  AlphaPlot::ColumnMode d_mode;
  //! The old data type
  AlphaPlot::ColumnDataType d_old_type;
  //! The new data type
  AlphaPlot::ColumnDataType d_new_type;
  //! Pointer to old data
  void* d_old_data;
  //! Pointer to new data
  void* d_new_data;
  //! The new input filter
  AbstractSimpleFilter* d_new_in_filter;
  //! The new output filter
  AbstractSimpleFilter* d_new_out_filter;
  //! The old input filter
  AbstractSimpleFilter* d_old_in_filter;
  //! The old output filter
  AbstractSimpleFilter* d_old_out_filter;
  //! The old validity information
  IntervalAttribute<bool> d_old_validity;
  //! The new validity information
  IntervalAttribute<bool> d_new_validity;
  //! A status flag
  bool d_undone;
  //! A status flag
  bool d_executed;
  //! Filter to use for converting existing data
  AbstractFilter* d_conversion_filter;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetModeCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnFullCopyCmd
///////////////////////////////////////////////////////////////////////////
//! Copy a complete column
class ColumnFullCopyCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnFullCopyCmd(Column::Private* col, const AbstractColumn* src,
                    QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnFullCopyCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The column to copy
  const AbstractColumn* d_src;
  //! A backup column
  Column::Private* d_backup;
  //! A dummy owner for the backup column
  /**
   * This is needed because a Column::Private must have an owner. We want access
   * to the Column::Private object to access its data pointer for fast data
   * replacement without too much copying.
   */
  Column* d_backup_owner;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnFullCopyCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnPartialCopyCmd
///////////////////////////////////////////////////////////////////////////
//! Copy parts of a column
class ColumnPartialCopyCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnPartialCopyCmd(Column::Private* col, const AbstractColumn* src,
                       int src_start, int dest_start, int num_rows,
                       QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnPartialCopyCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The column to copy
  const AbstractColumn* d_src;
  //! A backup of the orig. column
  Column::Private* d_col_backup;
  //! A backup of the source column
  Column::Private* d_src_backup;
  //! A dummy owner for the backup column
  /**
   * This is needed because a Column::Private must have an owner and
   * we must have a Column::Private object as backup.
   * Using a Column object as backup would lead to an inifinite loop.
   */
  Column* d_col_backup_owner;
  //! A dummy owner for the source backup column
  /**
   * This is needed because a Column::Private must have an owner and
   * we must have a Column::Private object as backup.
   * Using a Column object as backup would lead to an inifinite loop.
   */
  Column* d_src_backup_owner;
  //! Start index in source column
  int d_src_start;
  //! Start index in destination column
  int d_dest_start;
  //! Number of rows to copy
  int d_num_rows;
  //! Previous number of rows in the destination column
  int d_old_row_count;
  //! The old validity information
  IntervalAttribute<bool> d_old_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnPartialCopyCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnInsertEmptyRowsCmd
///////////////////////////////////////////////////////////////////////////
//! Insert empty rows
class ColumnInsertEmptyRowsCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnInsertEmptyRowsCmd(Column::Private* col, int before, int count,
                           QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnInsertEmptyRowsCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! Row to insert before
  int d_before;
  //! Number of rows
  int d_count;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnInsertEmptyRowsCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnRemoveRowsCmd
///////////////////////////////////////////////////////////////////////////
class ColumnRemoveRowsCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnRemoveRowsCmd(Column::Private* col, int first, int count,
                      QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnRemoveRowsCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The first row
  int d_first;
  //! The number of rows to be removed
  int d_count;
  //! Number of removed rows actually containing data
  int d_data_row_count;
  //! The number of rows before the removal
  int d_old_size;
  //! Column saving the removed rows
  Column::Private* d_backup;
  //! A dummy owner for the backup column
  /**
   * This is needed because a Column::Private must have an owner. We want access
   * to the Column::Private object to access its data pointer for fast data
   * replacement without too much copying.
   */
  Column* d_backup_owner;
  //! Backup of the masking attribute
  IntervalAttribute<bool> d_masking;
  //! Backup of the formula attribute
  IntervalAttribute<QString> d_formulas;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnRemoveRowsCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetPlotDesignationCmd
///////////////////////////////////////////////////////////////////////////
//! Sets a column's plot designation
class ColumnSetPlotDesignationCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetPlotDesignationCmd(Column::Private* col,
                              AlphaPlot::PlotDesignation pd,
                              QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetPlotDesignationCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! New plot designation
  AlphaPlot::PlotDesignation d_new_pd;
  //! Old plot designation
  AlphaPlot::PlotDesignation d_old_pd;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetPlotDesignationCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearCmd
///////////////////////////////////////////////////////////////////////////
//! Clear the column
class ColumnClearCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnClearCmd(Column::Private* col, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnClearCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The column's data type
  AlphaPlot::ColumnDataType d_type;
  //! Pointer to the old data pointer
  void* d_data;
  //! Pointer to an empty data vector
  void* d_empty_data;
  //! The old validity
  IntervalAttribute<bool> d_validity;
  //! Status flag
  bool d_undone;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearValidityCmd
///////////////////////////////////////////////////////////////////////////
//! Clear validity information
class ColumnClearValidityCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnClearValidityCmd(Column::Private* col, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnClearValidityCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The old validity
  IntervalAttribute<bool> d_validity;
  //! A status flag
  bool d_copied;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearValidityCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearMasksCmd
///////////////////////////////////////////////////////////////////////////
//! Clear validity information
class ColumnClearMasksCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnClearMasksCmd(Column::Private* col, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnClearMasksCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The old masks
  IntervalAttribute<bool> d_masking;
  //! A status flag
  bool d_copied;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearMasksCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetInvalidCmd
///////////////////////////////////////////////////////////////////////////
//! Mark an interval of rows as invalid
class ColumnSetInvalidCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetInvalidCmd(Column::Private* col, Interval<int> interval,
                      bool invalid, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetInvalidCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The interval
  Interval<int> d_interval;
  //! Valid/invalid flag
  bool d_invalid;
  //! Interval attribute backup
  IntervalAttribute<bool> d_validity;
  //! A status flag
  bool d_copied;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetInvalidCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetMaskedCmd
///////////////////////////////////////////////////////////////////////////
//! Mark an interval of rows as masked
class ColumnSetMaskedCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetMaskedCmd(Column::Private* col, Interval<int> interval, bool masked,
                     QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetMaskedCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The interval
  Interval<int> d_interval;
  //! Mask/unmask flag
  bool d_masked;
  //! Interval attribute backup
  IntervalAttribute<bool> d_masking;
  //! A status flag
  bool d_copied;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetMaskedCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetFormulaCmd
///////////////////////////////////////////////////////////////////////////
//! Set the formula for a given interval
class ColumnSetFormulaCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetFormulaCmd(Column::Private* col, Interval<int> interval,
                      const QString& formula, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetFormulaCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The interval
  Interval<int> d_interval;
  //! The new formula
  QString d_formula;
  //! Interval attribute backup
  IntervalAttribute<QString> d_formulas;
  //! A status flag
  bool d_copied;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetFormulaCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearFormulasCmd
///////////////////////////////////////////////////////////////////////////
//! Clear all associated formulas
class ColumnClearFormulasCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnClearFormulasCmd(Column::Private* col, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnClearFormulasCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The old formulas
  IntervalAttribute<QString> d_formulas;
  //! A status flag
  bool d_copied;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearFormulasCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetTextCmd
///////////////////////////////////////////////////////////////////////////
//! Set the text for a string cell
class ColumnSetTextCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetTextCmd(Column::Private* col, int row, const QString& new_value,
                   QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetTextCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The row to modify
  int d_row;
  //! The new value
  QString d_new_value;
  //! The old value
  QString d_old_value;
  //! The old number of rows
  int d_row_count;
  //! The old validity
  IntervalAttribute<bool> d_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetTextCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetValueCmd
///////////////////////////////////////////////////////////////////////////
//! Set the value for a double cell
class ColumnSetValueCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetValueCmd(Column::Private* col, int row, double new_value,
                    QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetValueCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The row to modify
  int d_row;
  //! The new value
  double d_new_value;
  //! The old value
  double d_old_value;
  //! The old number of rows
  int d_row_count;
  //! The old validity
  IntervalAttribute<bool> d_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetValueCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetDateTimeCmd
///////////////////////////////////////////////////////////////////////////
//! Set the value of a date-time cell
class ColumnSetDateTimeCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnSetDateTimeCmd(Column::Private* col, int row,
                       const QDateTime& new_value, QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnSetDateTimeCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The row to modify
  int d_row;
  //! The new value
  QDateTime d_new_value;
  //! The old value
  QDateTime d_old_value;
  //! The old number of rows
  int d_row_count;
  //! The old validity
  IntervalAttribute<bool> d_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetDateTimeCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnReplaceTextsCmd
///////////////////////////////////////////////////////////////////////////
//! Replace a range of strings in a string column
class ColumnReplaceTextsCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnReplaceTextsCmd(Column::Private* col, int first,
                        const QStringList& new_values,
                        QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnReplaceTextsCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The first row to replace
  int d_first;
  //! The new values
  QStringList d_new_values;
  //! The old values
  QStringList d_old_values;
  //! Status flag
  bool d_copied;
  //! The old number of rows
  int d_row_count;
  //! The old validity
  IntervalAttribute<bool> d_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnReplaceTextsCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnReplaceValuesCmd
///////////////////////////////////////////////////////////////////////////
//! Replace a range of doubles in a double column
class ColumnReplaceValuesCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnReplaceValuesCmd(Column::Private* col, int first,
                         const QVector<qreal>& new_values,
                         QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnReplaceValuesCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The first row to replace
  int d_first;
  //! The new values
  QVector<qreal> d_new_values;
  //! The old values
  QVector<qreal> d_old_values;
  //! Status flag
  bool d_copied;
  //! The old number of rows
  int d_row_count;
  //! The old validity
  IntervalAttribute<bool> d_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnReplaceValuesCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnReplaceDateTimesCmd
///////////////////////////////////////////////////////////////////////////
//! Replace a range of date-times in a date-time column
class ColumnReplaceDateTimesCmd : public QUndoCommand {
 public:
  //! Ctor
  ColumnReplaceDateTimesCmd(Column::Private* col, int first,
                            const QList<QDateTime>& new_values,
                            QUndoCommand* parent = 0);
  //! Dtor
  ~ColumnReplaceDateTimesCmd();

  //! Execute the command
  virtual void redo();
  //! Undo the command
  virtual void undo();

 private:
  //! The private column data to modify
  Column::Private* d_col;
  //! The first row to replace
  int d_first;
  //! The new values
  QList<QDateTime> d_new_values;
  //! The old values
  QList<QDateTime> d_old_values;
  //! Status flag
  bool d_copied;
  //! The old number of rows
  int d_row_count;
  //! The old validity
  IntervalAttribute<bool> d_validity;
};
///////////////////////////////////////////////////////////////////////////
// end of class ColumnReplaceDateTimesCmd
///////////////////////////////////////////////////////////////////////////

#endif  // COLUMNCOMMANDS_H
